

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=dark>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/fluid.png">
  <link rel="icon" href="/img/icon/dw.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Memory">
  <meta name="keywords" content="">
  
    <meta name="description" content="🎂 Java并发编程的秘密武器，解锁高性能并发之旅">
<meta property="og:type" content="article">
<meta property="og:title" content="Java线程池大揭秘：揭开并发编程的神秘面纱，让你的程序快到起飞">
<meta property="og:url" content="http://example.com/2023/10/22/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%A4%A7%E6%8F%AD%E7%A7%98%EF%BC%9A%E6%8F%AD%E5%BC%80%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E7%9A%84%E7%A5%9E%E7%A7%98%E9%9D%A2%E7%BA%B1%EF%BC%8C%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%A8%8B%E5%BA%8F%E5%BF%AB%E5%88%B0%E8%B5%B7%E9%A3%9E/index.html">
<meta property="og:site_name" content="Memory&#39;s blog">
<meta property="og:description" content="🎂 Java并发编程的秘密武器，解锁高性能并发之旅">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://example.com/img/artical/mountain.jpg">
<meta property="article:published_time" content="2023-10-22T08:08:32.000Z">
<meta property="article:modified_time" content="2024-01-09T14:34:43.000Z">
<meta property="article:author" content="Memory">
<meta property="article:tag" content="线程池">
<meta property="article:tag" content="并发编程">
<meta property="article:tag" content="JUC">
<meta property="article:tag" content="经验">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="http://example.com/img/artical/mountain.jpg">
  
  
  
  <title>Java线程池大揭秘：揭开并发编程的神秘面纱，让你的程序快到起飞 - Memory&#39;s blog</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"example.com","root":"/","version":"1.9.4","typing":{"enable":true,"typeSpeed":100,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":false,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":true,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
  

  

  

  

  

  

  

  



  
<meta name="generator" content="Hexo 5.4.2"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 75vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Memory&#39;s blog</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                <span>分类</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                <span>友链</span>
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/img/newBG/girl.jpg') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="Java线程池大揭秘：揭开并发编程的神秘面纱，让你的程序快到起飞"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        Memory
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2023-10-22 16:08" pubdate>
          2023年10月22日 下午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          19k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          49 分钟
        
      </span>
    

    
    
      
        <span id="leancloud-page-views-container" class="post-meta" style="display: none">
          <i class="iconfont icon-eye" aria-hidden="true"></i>
          <span id="leancloud-page-views"></span> 次
        </span>
        
      
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar category-bar" style="margin-right: -1rem">
    





<div class="category-list">
  
  
    
    
    
    <div class="category row nomargin-x">
      <a class="category-item 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="线程池"
        id="heading-46dc5c2e71218ed4b93a4940811ff549" role="tab" data-toggle="collapse" href="#collapse-46dc5c2e71218ed4b93a4940811ff549"
        aria-expanded="true"
      >
        线程池
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-46dc5c2e71218ed4b93a4940811ff549"
           role="tabpanel" aria-labelledby="heading-46dc5c2e71218ed4b93a4940811ff549">
        
        
          
          
  <div class="category-post-list">
    
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="并发编程"
        id="heading-1a9a671bb1da8c030da96f67497751c7" role="tab" data-toggle="collapse" href="#collapse-1a9a671bb1da8c030da96f67497751c7"
        aria-expanded="true"
      >
        并发编程
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-1a9a671bb1da8c030da96f67497751c7"
           role="tabpanel" aria-labelledby="heading-1a9a671bb1da8c030da96f67497751c7">
        
        
          
          
  <div class="category-post-list">
    
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="JUC"
        id="heading-afcda3fd308b15067b00b7804c7abba9" role="tab" data-toggle="collapse" href="#collapse-afcda3fd308b15067b00b7804c7abba9"
        aria-expanded="true"
      >
        JUC
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-afcda3fd308b15067b00b7804c7abba9"
           role="tabpanel" aria-labelledby="heading-afcda3fd308b15067b00b7804c7abba9">
        
        
          
          
  <div class="category-post-list">
    
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="经验"
        id="heading-32a8e000e928e6dc255876d9fc0178b3" role="tab" data-toggle="collapse" href="#collapse-32a8e000e928e6dc255876d9fc0178b3"
        aria-expanded="true"
      >
        经验
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-32a8e000e928e6dc255876d9fc0178b3"
           role="tabpanel" aria-labelledby="heading-32a8e000e928e6dc255876d9fc0178b3">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/2023/10/22/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%A4%A7%E6%8F%AD%E7%A7%98%EF%BC%9A%E6%8F%AD%E5%BC%80%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E7%9A%84%E7%A5%9E%E7%A7%98%E9%9D%A2%E7%BA%B1%EF%BC%8C%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%A8%8B%E5%BA%8F%E5%BF%AB%E5%88%B0%E8%B5%B7%E9%A3%9E/" title="Java线程池大揭秘：揭开并发编程的神秘面纱，让你的程序快到起飞"
           class="list-group-item list-group-item-action
           active">
          <span class="category-post">Java线程池大揭秘：揭开并发编程的神秘面纱，让你的程序快到起飞</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
        
      </div>
    </div>
  
        
      </div>
    </div>
  
        
      </div>
    </div>
  
</div>


  </aside>


    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Java线程池大揭秘：揭开并发编程的神秘面纱，让你的程序快到起飞</h1>
            
              <p class="note note-success">
                
                  
                    本文最后更新于：5 个月前
                  
                
              </p>
            
            
              <div class="markdown-body">
                
                <h1 id="破冰"><a href="#破冰" class="headerlink" title="破冰"></a>破冰</h1><ul>
<li><h5 id="🥇-推荐阅读：（2023-10-22晚）"><a href="#🥇-推荐阅读：（2023-10-22晚）" class="headerlink" title="🥇 推荐阅读：（2023/10/22晚）"></a>🥇 推荐阅读：（2023/10/22晚）</h5></li>
</ul>
<blockquote>
<h5 id="🔥-线程池："><a href="#🔥-线程池：" class="headerlink" title="🔥 线程池："></a>🔥 线程池：</h5><ul>
<li><h5 id="线程池都没搞懂，还敢说自己是程序员？-掘金-juejin-cn"><a href="#线程池都没搞懂，还敢说自己是程序员？-掘金-juejin-cn" class="headerlink" title="线程池都没搞懂，还敢说自己是程序员？ - 掘金 (juejin.cn)"></a><a target="_blank" rel="noopener" href="https://juejin.cn/post/7136524957374218248?from=search-suggest">线程池都没搞懂，还敢说自己是程序员？ - 掘金 (juejin.cn)</a></h5></li>
<li><h5 id="♨️别告诉我你连线程池都不会用！一文搞懂线程池-掘金-juejin-cn"><a href="#♨️别告诉我你连线程池都不会用！一文搞懂线程池-掘金-juejin-cn" class="headerlink" title="♨️别告诉我你连线程池都不会用！一文搞懂线程池 - 掘金 (juejin.cn)"></a><a target="_blank" rel="noopener" href="https://juejin.cn/post/7042107393668284452?searchId=2023102110045631FB8E0259EC00D79F5D">♨️别告诉我你连线程池都不会用！一文搞懂线程池 - 掘金 (juejin.cn)</a></h5></li>
<li><h5 id="java线程池ThreadPoolExecutor类使用详解-掘金-juejin-cn"><a href="#java线程池ThreadPoolExecutor类使用详解-掘金-juejin-cn" class="headerlink" title="java线程池ThreadPoolExecutor类使用详解 - 掘金 (juejin.cn)"></a><a target="_blank" rel="noopener" href="https://juejin.cn/post/6987576686472593415#heading-4">java线程池ThreadPoolExecutor类使用详解 - 掘金 (juejin.cn)</a></h5></li>
<li><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_38796327/article/details/90599867?ops_request_misc=%7B%22request_id%22:%22170000751816777224458220%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=170000751816777224458220&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-90599867-null-null.142%5Ev96%5Epc_search_result_base5&utm_term=@EnableAsync&spm=1018.2226.3001.4187">Springboot中的@EnableAsync和@Async的作用和基本用法-CSDN博客</a></p>
</li>
</ul>
</blockquote>
<blockquote>
<h5 id="💥-异步编程："><a href="#💥-异步编程：" class="headerlink" title="💥 异步编程："></a>💥 异步编程：</h5><ul>
<li><h5 id="异步编程利器：CompletableFuture详解-｜Java-开发实战-掘金-juejin-cn"><a href="#异步编程利器：CompletableFuture详解-｜Java-开发实战-掘金-juejin-cn" class="headerlink" title="异步编程利器：CompletableFuture详解 ｜Java 开发实战 - 掘金 (juejin.cn)"></a><a target="_blank" rel="noopener" href="https://juejin.cn/post/6970558076642394142?searchId=2023102123120702F3CCB4FA0222717C46">异步编程利器：CompletableFuture详解 ｜Java 开发实战 - 掘金 (juejin.cn)</a></h5></li>
<li><h5 id="深入解析CompletableFuture的功能和用法-掘金-juejin-cn"><a href="#深入解析CompletableFuture的功能和用法-掘金-juejin-cn" class="headerlink" title="深入解析CompletableFuture的功能和用法 - 掘金 (juejin.cn)"></a><a target="_blank" rel="noopener" href="https://juejin.cn/post/7255340317069541436">深入解析CompletableFuture的功能和用法 - 掘金 (juejin.cn)</a></h5></li>
<li><h5 id="CompletableFuture原理与实践-外卖商家端API的异步化-qq-com"><a href="#CompletableFuture原理与实践-外卖商家端API的异步化-qq-com" class="headerlink" title="CompletableFuture原理与实践-外卖商家端API的异步化 (qq.com)"></a><a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s/GQGidprakfticYnbVYVYGQ">CompletableFuture原理与实践-外卖商家端API的异步化 (qq.com)</a></h5></li>
</ul>
<h5 id="🍖-锁："><a href="#🍖-锁：" class="headerlink" title="🍖 锁："></a>🍖 锁：</h5><ul>
<li><h5 id="两万字详解！InnoDB锁专题！-qq-com"><a href="#两万字详解！InnoDB锁专题！-qq-com" class="headerlink" title="两万字详解！InnoDB锁专题！ (qq.com)"></a><a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s?__biz=MzkyMzU5Mzk1NQ==&mid=2247506461&idx=1&sn=ff71cb615ecea4df64b8d42701a05243&source=41#wechat_redirect">两万字详解！InnoDB锁专题！ (qq.com)</a></h5></li>
<li><h5 id="数据库锁的12连问，你顶得了嘛？-掘金-juejin-cn"><a href="#数据库锁的12连问，你顶得了嘛？-掘金-juejin-cn" class="headerlink" title="数据库锁的12连问，你顶得了嘛？ - 掘金 (juejin.cn)"></a><a target="_blank" rel="noopener" href="https://juejin.cn/post/7199666255884009532">数据库锁的12连问，你顶得了嘛？ - 掘金 (juejin.cn)</a></h5></li>
</ul>
</blockquote>
<p>线程池<br>线程池的创建（参数）<br>线程池的运行机制（理论 + 演示）<br>线程池的使用（实战 submit + CompatableFuture异步）</p>
<h1 id="精髓所在"><a href="#精髓所在" class="headerlink" title="精髓所在"></a>精髓所在</h1><h2 id="线程基础"><a href="#线程基础" class="headerlink" title="线程基础"></a>线程基础</h2><blockquote>
<h5 id="🔥-推荐阅读：Java开发-不知道算不算详细的JUC详解-java-juc-CodingFire的博客-CSDN博客"><a href="#🔥-推荐阅读：Java开发-不知道算不算详细的JUC详解-java-juc-CodingFire的博客-CSDN博客" class="headerlink" title="🔥 推荐阅读：Java开发 - 不知道算不算详细的JUC详解_java juc_CodingFire的博客-CSDN博客"></a>🔥 推荐阅读：<a target="_blank" rel="noopener" href="https://codingfire.blog.csdn.net/article/details/130361371">Java开发 - 不知道算不算详细的JUC详解_java juc_CodingFire的博客-CSDN博客</a></h5></blockquote>
<h3 id="线程状态总结"><a href="#线程状态总结" class="headerlink" title="线程状态总结"></a>线程状态总结</h3><p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/44112f25bc1a42b1805dcd0de1239267.png"></p>
<h3 id="Java-创建线程的十种方式"><a href="#Java-创建线程的十种方式" class="headerlink" title="Java 创建线程的十种方式"></a>Java 创建线程的十种方式</h3><blockquote>
<p>🌮 推荐阅读：<a target="_blank" rel="noopener" href="https://juejin.cn/post/7241395267797942329">大家都说Java有三种创建线程的方式！并发编程中的惊天骗局！ - 掘金 (juejin.cn)</a></p>
</blockquote>
<h4 id="继承-Thread-类"><a href="#继承-Thread-类" class="headerlink" title="继承 Thread 类"></a>继承 Thread 类</h4><ul>
<li><h5 id="代码示例：（2023-11-11早）"><a href="#代码示例：（2023-11-11早）" class="headerlink" title="代码示例：（2023/11/11早）"></a>代码示例：（2023/11/11早）</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 9:30</span><br><span class="hljs-comment"> * Function: 继承 Thread 类</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ExtendsThread</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Thread</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">run</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;1......&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">ExtendsThread</span>().start();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="运行结果："><a href="#运行结果：" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111101903672.png" alt="image-20231111101903672"></p>
<h4 id="实现-Runnable-接口"><a href="#实现-Runnable-接口" class="headerlink" title="实现 Runnable 接口"></a>实现 Runnable 接口</h4><ul>
<li><h5 id="代码示例："><a href="#代码示例：" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 9:32</span><br><span class="hljs-comment"> * Function: 实现 Runnable 接口</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ImplementsRunnable</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">Runnable</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">run</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;2.....&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ImplementsRunnable</span>()).start();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="运行结果：-1"><a href="#运行结果：-1" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111102014242.png" alt="image-20231111102014242"></p>
<h4 id="实现-Callable-接口"><a href="#实现-Callable-接口" class="headerlink" title="实现 Callable 接口"></a>实现 Callable 接口</h4><ul>
<li><h5 id="代码示例：-1"><a href="#代码示例：-1" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 9:33</span><br><span class="hljs-comment"> * Function: 实现 Callable 接口</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ImplementsCallable</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">Callable</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Object <span class="hljs-title function_">call</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;3....&quot;</span>);<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;hhh&quot;</span>;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        FutureTask&lt;String&gt; futureTask = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FutureTask</span>&lt;&gt;(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ImplementsCallable</span>());<br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(futureTask).start();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="运行结果：-2"><a href="#运行结果：-2" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111102052773.png" alt="image-20231111102052773"></p>
<h4 id="使用-ExecutorService-线程池"><a href="#使用-ExecutorService-线程池" class="headerlink" title="使用 ExecutorService 线程池"></a>使用 ExecutorService 线程池</h4><ul>
<li><h5 id="代码示例：-2"><a href="#代码示例：-2" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 9:37</span><br><span class="hljs-comment"> * Function: 使用 ExecutorService 线程池</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UseExecutorsService</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-comment">// 1.自定义线程池</span><br>        <span class="hljs-type">ThreadPoolExecutor</span> <span class="hljs-variable">threadPoolB</span> <span class="hljs-operator">=</span><br>                <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadPoolExecutor</span>(<span class="hljs-number">3</span>, <span class="hljs-number">5</span>,<br>                        <span class="hljs-number">0</span>, TimeUnit.SECONDS, <span class="hljs-keyword">new</span> <span class="hljs-title class_">LinkedBlockingDeque</span>&lt;Runnable&gt;(<span class="hljs-number">4</span>),<br>                        Executors.defaultThreadFactory(), <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadPoolExecutor</span>.AbortPolicy());<br><br>        threadPoolB.submit(() -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;4B......&quot;</span>);<br>        &#125;);<br>        threadPoolB.shutdown();<br><br>        <span class="hljs-comment">// 2.Executors 线程池</span><br>        <span class="hljs-type">ExecutorService</span> <span class="hljs-variable">threadPoolA</span> <span class="hljs-operator">=</span> Executors.newFixedThreadPool(<span class="hljs-number">5</span>);<br><br>        <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) &#123;<br>            threadPoolA.execute(() -&gt; &#123;<br>                System.out.println(<span class="hljs-string">&quot;4.1....&quot;</span> + Thread.currentThread().getName());<br>            &#125;);<br>            <span class="hljs-keyword">try</span> &#123;<br>                Thread.sleep(<span class="hljs-number">1000</span>);<br>            &#125; <span class="hljs-keyword">catch</span> (InterruptedException e) &#123;<br>                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(e);<br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="运行结果：-3"><a href="#运行结果：-3" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111102231708.png" alt="image-20231111102231708"></p>
<h4 id="使用-CompletableFuture-类"><a href="#使用-CompletableFuture-类" class="headerlink" title="使用 CompletableFuture 类"></a>使用 CompletableFuture 类</h4><ul>
<li><h5 id="代码示例：-3"><a href="#代码示例：-3" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 9:53</span><br><span class="hljs-comment"> * Function: 使用 CompletableFuture 类</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UseCompletableFuture</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        CompletableFuture.supplyAsync(() -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;5.1....&quot;</span>);<br>            <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;hhh&quot;</span>;<br>        &#125;);<br><br>        CompletableFuture.runAsync(() -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;5.2....&quot;</span>);<br>        &#125;);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="运行结果：-4"><a href="#运行结果：-4" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111102428953.png" alt="image-20231111102428953"></p>
<h4 id="基于-ThreadGroup-线程组"><a href="#基于-ThreadGroup-线程组" class="headerlink" title="基于 ThreadGroup 线程组"></a>基于 ThreadGroup 线程组</h4><ul>
<li><h5 id="代码示例：-4"><a href="#代码示例：-4" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 9:59</span><br><span class="hljs-comment"> * Function: 基于 ThreadGroup 线程组</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UseThreadGroup</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">ThreadGroup</span> <span class="hljs-variable">threadGroup</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadGroup</span>(<span class="hljs-string">&quot;groupName&quot;</span>);<br><br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(threadGroup, () -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;6....&quot;</span> + Thread.currentThread().getName());<br>        &#125;).start();<br><br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(threadGroup, () -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;6....&quot;</span> + Thread.currentThread().getName());<br>        &#125;,<span class="hljs-string">&quot;T2&quot;</span>).start();<br><br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(threadGroup, () -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;6....&quot;</span> + Thread.currentThread().getName());<br>        &#125;).start();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="运行结果：-5"><a href="#运行结果：-5" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111102525557.png" alt="image-20231111102525557"></p>
<h4 id="使用-FutureTask-类"><a href="#使用-FutureTask-类" class="headerlink" title="使用 FutureTask 类"></a>使用 FutureTask 类</h4><ul>
<li><h5 id="代码示例：-5"><a href="#代码示例：-5" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 10:02</span><br><span class="hljs-comment"> * Function: 使用 FutureTask 类</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UseFutureTask</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        FutureTask&lt;String&gt; futureTask = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FutureTask</span>&lt;&gt;(() -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;7....&quot;</span>);<br>            <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;hhh&quot;</span>;<br>        &#125;);<br><br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(futureTask).start();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="运行结果：-6"><a href="#运行结果：-6" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111102608295.png" alt="image-20231111102608295"></p>
<h4 id="使用匿名内部类或-Lambda-表达式"><a href="#使用匿名内部类或-Lambda-表达式" class="headerlink" title="使用匿名内部类或 Lambda 表达式"></a>使用匿名内部类或 Lambda 表达式</h4><ul>
<li><h5 id="代码示例：-6"><a href="#代码示例：-6" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 10:05</span><br><span class="hljs-comment"> * Function: 使用匿名内部类或 Lambda 表达式</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UseAnonymousClass</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Runnable</span>() &#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">run</span><span class="hljs-params">()</span> &#123;<br>                System.out.println(<span class="hljs-string">&quot;8....&quot;</span>);<br>            &#125;<br>        &#125;).start();<br><br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(() -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;8....&quot;</span>);<br>        &#125;).start();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="运行结果：-7"><a href="#运行结果：-7" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111102656656.png" alt="image-20231111102656656"></p>
<h4 id="使用-Timer-定时器类"><a href="#使用-Timer-定时器类" class="headerlink" title="使用 Timer 定时器类"></a>使用 Timer 定时器类</h4><ul>
<li><h5 id="代码示例：-7"><a href="#代码示例：-7" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 10:07</span><br><span class="hljs-comment"> * Function: 使用 Timer 定时器类</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UseTimer</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Timer</span> <span class="hljs-variable">timer</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Timer</span>();<br>        timer.schedule(<span class="hljs-keyword">new</span> <span class="hljs-title class_">TimerTask</span>() &#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">run</span><span class="hljs-params">()</span> &#123;<br>                System.out.println(<span class="hljs-string">&quot;9....&quot;</span>);<br>            &#125;<br>        &#125;, <span class="hljs-number">2000</span>, <span class="hljs-number">1000</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><p>在 <code>《打造流畅编码之旅：IntelliJ IDEA 的高效使用技巧与工作流程优化》</code> 一文中 <code>定时任务实现</code> 栏目下有过详细的扩展讲解</p>
</li>
<li><h5 id="运行结果：-8"><a href="#运行结果：-8" class="headerlink" title="运行结果："></a>运行结果：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231111101645358.png" alt="image-20231111101645358"></p>
<h4 id="使用-ForkJoin-线程池或-Stream-并行流"><a href="#使用-ForkJoin-线程池或-Stream-并行流" class="headerlink" title="使用 ForkJoin 线程池或 Stream 并行流"></a>使用 ForkJoin 线程池或 Stream 并行流</h4><ul>
<li><h5 id="代码示例：-8"><a href="#代码示例：-8" class="headerlink" title="代码示例："></a>代码示例：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/11/11 10:10</span><br><span class="hljs-comment"> * Function: 使用 ForkJoin 线程池或 Stream 并行流</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UseForkJoinPool</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">ForkJoinPool</span> <span class="hljs-variable">joinPool</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ForkJoinPool</span>();<br><br>        joinPool.execute(() -&gt; &#123;<br>            System.out.println(<span class="hljs-string">&quot;10....&quot;</span>);<br>        &#125;);<br>        <br>        List&lt;String&gt; list = Arrays.asList(<span class="hljs-string">&quot;10B......&quot;</span>);<br>        list.parallelStream().forEach(System.out::println);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h2 id="线程池"><a href="#线程池" class="headerlink" title="线程池"></a>线程池</h2><h3 id="使用线程池的优势"><a href="#使用线程池的优势" class="headerlink" title="使用线程池的优势"></a>使用线程池的优势</h3><h3 id="构造线程池"><a href="#构造线程池" class="headerlink" title="构造线程池"></a>构造线程池</h3><h4 id="核心参数介绍"><a href="#核心参数介绍" class="headerlink" title="核心参数介绍"></a>核心参数介绍</h4><ul>
<li><h5 id="corePoolSize（核心线程数）（2023-10-22晚）"><a href="#corePoolSize（核心线程数）（2023-10-22晚）" class="headerlink" title="corePoolSize（核心线程数）（2023/10/22晚）"></a>corePoolSize（核心线程数）（2023/10/22晚）</h5></li>
<li><h5 id="maximumPoolSize（最大线程数）"><a href="#maximumPoolSize（最大线程数）" class="headerlink" title="maximumPoolSize（最大线程数）"></a>maximumPoolSize（最大线程数）</h5></li>
<li><h5 id="keepAliveTime（闲置超时时长）"><a href="#keepAliveTime（闲置超时时长）" class="headerlink" title="keepAliveTime（闲置超时时长）"></a>keepAliveTime（闲置超时时长）</h5></li>
<li><h5 id="unit（闲置超时单位）"><a href="#unit（闲置超时单位）" class="headerlink" title="unit（闲置超时单位）"></a>unit（闲置超时单位）</h5></li>
<li><h5 id="workQueue（任务队列）"><a href="#workQueue（任务队列）" class="headerlink" title="workQueue（任务队列）"></a>workQueue（任务队列）</h5></li>
<li><h5 id="threadFactory（线程工厂）"><a href="#threadFactory（线程工厂）" class="headerlink" title="threadFactory（线程工厂）"></a>threadFactory（线程工厂）</h5></li>
<li><h5 id="handler（拒绝策略）"><a href="#handler（拒绝策略）" class="headerlink" title="handler（拒绝策略）"></a>handler（拒绝策略）</h5></li>
</ul>
<h3 id="线程池的工作原理"><a href="#线程池的工作原理" class="headerlink" title="线程池的工作原理"></a>线程池的工作原理</h3><h4 id="图文介绍"><a href="#图文介绍" class="headerlink" title="图文介绍"></a>图文介绍</h4><h4 id="实操测试"><a href="#实操测试" class="headerlink" title="实操测试"></a>实操测试</h4><ul>
<li><p>这里我们简单演示下线程池的工作原理，按如下步骤依次进行</p>
</li>
<li><h5 id="自定义线程工厂（2023-10-22晚）"><a href="#自定义线程工厂（2023-10-22晚）" class="headerlink" title="自定义线程工厂（2023/10/22晚）"></a>自定义线程工厂（2023/10/22晚）</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * 2023/10/16</span><br><span class="hljs-comment"> * Function: 自定义线程池</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ThreadPoolExecutorConfig</span> &#123;<br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> ThreadPoolExecutor <span class="hljs-title function_">threadPoolExecutor</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-type">ThreadFactory</span> <span class="hljs-variable">threadFactory</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadFactory</span>() &#123;<br>            <span class="hljs-comment">// 记录线程数</span><br>            <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> <span class="hljs-variable">count</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br><br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-keyword">public</span> Thread <span class="hljs-title function_">newThread</span><span class="hljs-params">(Runnable r)</span> &#123;<br>                <span class="hljs-type">Thread</span> <span class="hljs-variable">thread</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(r);<br>                thread.setName(<span class="hljs-string">&quot;线程&quot;</span> + count);<br>                count++;<br>                <span class="hljs-keyword">return</span> thread;<br>            &#125;<br>        &#125;;<br><br>        <span class="hljs-type">ThreadPoolExecutor</span> <span class="hljs-variable">threadPoolExecutor</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadPoolExecutor</span><br>                (<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">100</span>,<br>                        TimeUnit.MINUTES, <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayBlockingQueue</span>&lt;&gt;(<span class="hljs-number">4</span>), threadFactory);<br>        <span class="hljs-keyword">return</span> threadPoolExecutor;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="注入自定义线程工厂依赖"><a href="#注入自定义线程工厂依赖" class="headerlink" title="注入自定义线程工厂依赖"></a>注入自定义线程工厂依赖</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 邓哈哈</span><br><span class="hljs-comment"> * Function: 任务队列测试 提交任务到线程池</span><br><span class="hljs-comment"> * Version 1.0</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-meta">@RestController</span><br><span class="hljs-meta">@RequestMapping(&quot;/queue&quot;)</span><br><span class="hljs-meta">@Slf4j</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">QueueController</span> &#123;<br>    <span class="hljs-meta">@Resource</span><br>    <span class="hljs-keyword">private</span> ThreadPoolExecutor threadPoolExecutor;<br>...............................<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="编写接口：查看当前线程池状态、新增线程"><a href="#编写接口：查看当前线程池状态、新增线程" class="headerlink" title="编写接口：查看当前线程池状态、新增线程"></a>编写接口：查看当前线程池状态、新增线程</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@GetMapping(&quot;/get&quot;)</span><br>   <span class="hljs-keyword">public</span> String <span class="hljs-title function_">get</span><span class="hljs-params">()</span> &#123;<br>       HashMap&lt;String, Object&gt; map = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span>&lt;&gt;();<br>       <span class="hljs-type">int</span> <span class="hljs-variable">size</span> <span class="hljs-operator">=</span> threadPoolExecutor.getQueue().size();<br>       map.put(<span class="hljs-string">&quot;队列长度&quot;</span>, size);<br>       <span class="hljs-type">long</span> <span class="hljs-variable">taskCount</span> <span class="hljs-operator">=</span> threadPoolExecutor.getTaskCount();<br>       map.put(<span class="hljs-string">&quot;任务总数&quot;</span>, taskCount);<br>       <span class="hljs-type">long</span> <span class="hljs-variable">completedTaskCount</span> <span class="hljs-operator">=</span> threadPoolExecutor.getCompletedTaskCount();<br>       map.put(<span class="hljs-string">&quot;已完成任务数&quot;</span>, completedTaskCount);<br>       <span class="hljs-type">int</span> <span class="hljs-variable">activeCount</span> <span class="hljs-operator">=</span> threadPoolExecutor.getActiveCount();<br>       map.put(<span class="hljs-string">&quot;正在工作的线程数&quot;</span>, activeCount);<br>       <span class="hljs-keyword">return</span> JSONUtil.toJsonStr(map);<br>   &#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@GetMapping(&quot;/add&quot;)</span><br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">add</span><span class="hljs-params">(String name)</span> &#123;<br>     CompletableFuture.runAsync(() -&gt; &#123;<br>         log.info(Thread.currentThread().getName() + <span class="hljs-string">&quot;正在执行中&quot;</span>);<br>         <span class="hljs-keyword">try</span> &#123;<br>             Thread.sleep(<span class="hljs-number">600000</span>);<br>         &#125; <span class="hljs-keyword">catch</span> (InterruptedException e) &#123;<br>             e.printStackTrace();<br>         &#125;<br>     &#125;, threadPoolExecutor);<br> &#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="开启测试（2023-10-22晚）"><a href="#开启测试（2023-10-22晚）" class="headerlink" title="开启测试（2023/10/22晚）"></a>开启测试（2023/10/22晚）</h5></li>
<li><p>详细的流程介绍可以在《简单测试，理解线程池的工作流程》一栏中学习了解<strong>（2023/12/22早）</strong></p>
</li>
</ul>
<h3 id="其他参数介绍"><a href="#其他参数介绍" class="headerlink" title="其他参数介绍"></a>其他参数介绍</h3><h4 id="阻塞队列"><a href="#阻塞队列" class="headerlink" title="阻塞队列"></a>阻塞队列</h4><h4 id="线程工厂与自定义工厂"><a href="#线程工厂与自定义工厂" class="headerlink" title="线程工厂与自定义工厂"></a>线程工厂与自定义工厂</h4><h4 id="拒绝策略与自定义策略"><a href="#拒绝策略与自定义策略" class="headerlink" title="拒绝策略与自定义策略"></a>拒绝策略与自定义策略</h4><h4 id="线程池的工作机制"><a href="#线程池的工作机制" class="headerlink" title="线程池的工作机制"></a>线程池的工作机制</h4><ul>
<li>这部分内容我计划在新的博文中介绍，可以看这篇文章学习：</li>
</ul>
<blockquote>
<p>🥣 推荐阅读：</p>
<ul>
<li><h5 id="Java-线程池详解-JavaGuide-Java面试-学习指南"><a href="#Java-线程池详解-JavaGuide-Java面试-学习指南" class="headerlink" title="Java 线程池详解 | JavaGuide(Java面试 + 学习指南)"></a><a target="_blank" rel="noopener" href="https://javaguide.cn/java/concurrent/java-thread-pool-summary.html">Java 线程池详解 | JavaGuide(Java面试 + 学习指南)</a></h5></li>
</ul>
</blockquote>
<h3 id="简单测试，理解线程池工作流程"><a href="#简单测试，理解线程池工作流程" class="headerlink" title="简单测试，理解线程池工作流程"></a>简单测试，理解线程池工作流程</h3><h4 id="自定义线程池"><a href="#自定义线程池" class="headerlink" title="自定义线程池"></a>自定义线程池</h4><ul>
<li>自定义线程池：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 自定义线程池</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ThreadPoolExecutorConfig</span> &#123;<br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> ThreadPoolExecutor <span class="hljs-title function_">threadPoolExecutor</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-type">ThreadFactory</span> <span class="hljs-variable">threadFactory</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadFactory</span>() &#123;<br>            <span class="hljs-comment">// 记录线程数</span><br>            <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> <span class="hljs-variable">count</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-keyword">public</span> Thread <span class="hljs-title function_">newThread</span><span class="hljs-params">(<span class="hljs-meta">@NotNull</span> Runnable r)</span> &#123;<br>                <span class="hljs-type">Thread</span> <span class="hljs-variable">thread</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(r);<br>                thread.setName(<span class="hljs-string">&quot;线程&quot;</span> + count);<br>                count++;<br>                <span class="hljs-keyword">return</span> thread;<br>            &#125;<br>        &#125;;<br>        <span class="hljs-type">ThreadPoolExecutor</span> <span class="hljs-variable">threadPoolExecutor</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadPoolExecutor</span><br>                (<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">100</span>,<br>                        TimeUnit.MINUTES, <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayBlockingQueue</span>&lt;&gt;(<span class="hljs-number">4</span>), threadFactory);<br>        <span class="hljs-keyword">return</span> threadPoolExecutor;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>在代码中，首先定义了一个<strong>ThreadFactory接口的实现类</strong>，用于<strong>创建线程</strong>。<strong>（2023/10/15晚）</strong></li>
<li>在<strong>newThread方法</strong>中，通过创建线程并设置名称的方式来<strong>实现线程的创建</strong>。每次创建线程时，都会使用一个计数器count，用于记录线程的数量，保证<strong>线程名称的唯一性</strong>。</li>
<li>然后，使用ThreadPoolExecutor类创建一个<strong>线程池对象</strong>。括号内的参数依次为：<strong>核心线程数、最大线程数、线程空闲时间、时间单位、任务队列以及线程工厂</strong>。这些参数分别表示线程池的基本配置，如最小/最大线程数、线程空闲时间等。其中，任务队列使用了ArrayBlockingQueue，表示<strong>使用有界队列来存储线程任务</strong>。</li>
<li>最后，<strong>将创建好的线程池对象返回</strong>，供其他地方进行调用和使用。</li>
</ul>
<h4 id="提交任务到线程池"><a href="#提交任务到线程池" class="headerlink" title="提交任务到线程池"></a>提交任务到线程池</h4><ul>
<li>提交任务到线程池：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 任务队列测试 提交任务到线程池</span><br><span class="hljs-comment"> */</span><br><span class="hljs-meta">@RestController</span><br><span class="hljs-meta">@RequestMapping(&quot;/queue&quot;)</span><br><span class="hljs-meta">@Slf4j</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">QueueController</span> &#123;<br>    <span class="hljs-meta">@Resource</span><br>    <span class="hljs-keyword">private</span> ThreadPoolExecutor threadPoolExecutor;<br><br>    <span class="hljs-meta">@GetMapping(&quot;/get&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">get</span><span class="hljs-params">()</span> &#123;<br>        HashMap&lt;String, Object&gt; map = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span>&lt;&gt;();<br>        <span class="hljs-type">int</span> <span class="hljs-variable">size</span> <span class="hljs-operator">=</span> threadPoolExecutor.getQueue().size();<br>        map.put(<span class="hljs-string">&quot;队列长度&quot;</span>, size);<br>        <span class="hljs-type">long</span> <span class="hljs-variable">taskCount</span> <span class="hljs-operator">=</span> threadPoolExecutor.getTaskCount();<br>        map.put(<span class="hljs-string">&quot;任务总数&quot;</span>, taskCount);<br>        <span class="hljs-type">long</span> <span class="hljs-variable">completedTaskCount</span> <span class="hljs-operator">=</span> threadPoolExecutor.getCompletedTaskCount();<br>        map.put(<span class="hljs-string">&quot;已完成任务数&quot;</span>, completedTaskCount);<br>        <span class="hljs-type">int</span> <span class="hljs-variable">activeCount</span> <span class="hljs-operator">=</span> threadPoolExecutor.getActiveCount();<br>        map.put(<span class="hljs-string">&quot;正在工作的线程数&quot;</span>, activeCount);<br>        <span class="hljs-keyword">return</span> JSONUtil.toJsonStr(map);<br>    &#125;<br><br>    <span class="hljs-meta">@GetMapping(&quot;/add&quot;)</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">add</span><span class="hljs-params">(String name)</span> &#123;<br>        CompletableFuture.runAsync(() -&gt; &#123;<br>            log.info(Thread.currentThread().getName() + <span class="hljs-string">&quot;正在执行中&quot;</span>);<br>            <span class="hljs-keyword">try</span> &#123;<br>                Thread.sleep(<span class="hljs-number">600000</span>);<br>            &#125; <span class="hljs-keyword">catch</span> (InterruptedException e) &#123;<br>                e.printStackTrace();<br>            &#125;<br>        &#125;, threadPoolExecutor);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><p>这段代码是一个简单的示例，在<strong>Spring Boot中使用自定义的线程池</strong>。首先通过@Resource注解将之前配置好的线程池对象threadPoolExecutor注入进来，然后定义了<strong>两个接口方法：get和add</strong>。</p>
</li>
<li><p>在get方法中，通过调用线程池对象的不同方法，<strong>获取了线程池的一些状态信息</strong>，如<strong>队列长度、任务总数、已完成任务数和正在工作的线程数</strong>，并将这些信息封装进一个<strong>HashMap</strong>中，最后<strong>使用 JSONUtil.toJsonStr 方法将其转换成JSON格式的字符串</strong>返回。</p>
</li>
<li><p>在add方法中，使用 <strong>CompletableFuture.runAsync 方法来在线程池中执行一个任务</strong>。这里的任务是一个简单的代码块，通过log输出当前线程的名称，并休眠10分钟。通过将线程池对象threadPoolExecutor作为参数传递给runAsync方法，使得任务在该线程池中执行。</p>
</li>
<li><p>通过这段代码，我们可以在Spring Boot项目中方便地<strong>使用自定义的线程池，并对其进行状态监控和管理</strong>。<strong>（2023/10/15晚）</strong></p>
</li>
<li><p>由 ThreadPoolExecutorConfig 配置可知，我们自定义的线程池参数设置如下：</p>
<ul>
<li><h5 id="核心线程数：2"><a href="#核心线程数：2" class="headerlink" title="核心线程数：2"></a>核心线程数：2</h5></li>
<li><h5 id="最大线程数：4"><a href="#最大线程数：4" class="headerlink" title="最大线程数：4"></a>最大线程数：4</h5></li>
<li><h5 id="任务队列数：4"><a href="#任务队列数：4" class="headerlink" title="任务队列数：4"></a>任务队列数：4</h5></li>
<li><h5 id="超时等待时间：未设置，默认拒绝"><a href="#超时等待时间：未设置，默认拒绝" class="headerlink" title="超时等待时间：未设置，默认拒绝"></a>超时等待时间：未设置，默认拒绝</h5></li>
<li><h5 id="时间单位：秒（SECEND）"><a href="#时间单位：秒（SECEND）" class="headerlink" title="时间单位：秒（SECEND）"></a>时间单位：秒（SECEND）</h5></li>
</ul>
</li>
<li><p>我们开始测试，依次添加任务，观察执行的线程数和任务队列数，详情如下：</p>
</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231015192743819.png" alt="image-20231015192743819"></p>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231015192927650.png" alt="image-20231015192927650"></p>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231015193033848.png" alt="image-20231015193033848"></p>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20231015193106483.png" alt="image-20231015193106483"></p>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231015193134223.png" alt="image-20231015193134223"></p>
<ul>
<li><p>简单描述一下测试情况吧：</p>
<ul>
<li>当<strong>正在运行的线程数未达到核心线程数阈值</strong>时，优先添加线程处理新任务</li>
<li>当<strong>正在运行的线程数达到核心线程数阈值，但任务队列未满</strong>时，优先将任务放入任务队列中</li>
<li>当<strong>任务队列放满后，但正在运行的线程数未达到最大线程数阈值</strong>时，优先添加线程处理新任务</li>
<li>当<strong>正在运行的线程数达到最大线程数阈值后</strong>，采用合适的拒绝策略（这里我们采用默认的拒绝策略：直接扔掉这个任务）</li>
</ul>
</li>
<li><h5 id="测试完成（2023-10-15晚）"><a href="#测试完成（2023-10-15晚）" class="headerlink" title="测试完成（2023/10/15晚）"></a>测试完成（2023/10/15晚）</h5></li>
</ul>
<h3 id="真实业务场景下的实战"><a href="#真实业务场景下的实战" class="headerlink" title="真实业务场景下的实战"></a>真实业务场景下的实战</h3><h4 id="批量插入用户记录"><a href="#批量插入用户记录" class="headerlink" title="批量插入用户记录"></a>批量插入用户记录</h4><ul>
<li><p>这个需求场景是我在做 Memory 伙伴匹配系统 时遇到的：<strong>批量插入用户记录</strong></p>
</li>
<li><p>新建 <code>StopWatch</code> 对象，计时开始：<strong>（2024/01/09晚）</strong></p>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// new一个StopWatch对象</span><br><span class="hljs-type">StopWatch</span> <span class="hljs-variable">stopWatch</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">StopWatch</span>();<br><span class="hljs-comment">// 计时开始</span><br>stopWatch.start();<br></code></pre></td></tr></table></figure>

<ul>
<li>限制可创建的最大线程数量，限制每个线程最大可插入的用户记录条数：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 每条线程插入1000条</span><br><span class="hljs-type">int</span> <span class="hljs-variable">batchSize</span> <span class="hljs-operator">=</span> <span class="hljs-number">1000</span>;<br><span class="hljs-comment">// 最大线程数为 10 条</span><br><span class="hljs-type">int</span> <span class="hljs-variable">maxSize</span> <span class="hljs-operator">=</span> <span class="hljs-number">100</span>;<br></code></pre></td></tr></table></figure>

<ul>
<li>异步条件下，执行批量插入，并使用异步任务集合 <code>futureList</code> 维护所有正在执行中的异步任务：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 开10条线程</span><br>        <span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>, j = <span class="hljs-number">0</span>; i &lt; maxSize; i++) &#123;<br>            <span class="hljs-comment">// 每条线程下new一个userList</span><br>            ArrayList&lt;User&gt; userList = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;&gt;();<br>            <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) &#123;<br>                j++;<br>                <span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();<br>                user.setUserAccount(<span class="hljs-string">&quot;memory&quot;</span> + <span class="hljs-string">&quot;_&quot;</span> + (UUID.randomUUID() + <span class="hljs-string">&quot;&quot;</span>).substring(<span class="hljs-number">0</span>, <span class="hljs-number">8</span>));<br>                <span class="hljs-type">String</span> <span class="hljs-variable">password</span> <span class="hljs-operator">=</span> DigestUtils.md5DigestAsHex((SALT + <span class="hljs-number">12345678</span>).getBytes());<br>                user.setUserPassword(password);<br>                user.setAvatarUrl(<span class="hljs-string">&quot;https://fastly.jsdelivr.net/npm/@vant/assets/ipad.jpeg&quot;</span>);<br>                user.setGender(<span class="hljs-string">&quot;0&quot;</span>);<br>                user.setPhone(<span class="hljs-string">&quot;18535854763&quot;</span>);<br>                user.setEmail(<span class="hljs-string">&quot;3348407547@qq.com&quot;</span>);<br>                user.setUserStatus(<span class="hljs-number">0</span>);<br>                user.setUserRole(<span class="hljs-number">0</span>);<br>                user.setPlanetCode(<span class="hljs-string">&quot;17625&quot;</span>);<br>                user.setTags(<span class="hljs-string">&quot;[\&quot;女\&quot;,\&quot;Vue\&quot;,\&quot;Python\&quot;,\&quot;在校本科\&quot;,\&quot;发呆\&quot;,\&quot;emo中\&quot;]&quot;</span>);<br>                userList.add(user);<br>                <span class="hljs-comment">// 当该线程插满1000条数据，便退出该线程循环</span><br>                <span class="hljs-keyword">if</span> (j % batchSize == <span class="hljs-number">0</span>) &#123;<br>                    <span class="hljs-keyword">break</span>;<br>                &#125;<br>            &#125;<br>            <span class="hljs-comment">// 异步条件下, 执行批量插入</span><br>            CompletableFuture&lt;Void&gt; future = CompletableFuture.runAsync(() -&gt; &#123;<br>                System.out.println(<span class="hljs-string">&quot;threadName: &quot;</span> + Thread.currentThread().getName());<br>                userService.saveBatch(userList, batchSize);<br>            &#125;);<br>            <span class="hljs-comment">// 将该任务存储到异步任务集合当中</span><br>            futureList.add(future);<br>        &#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>结束所有异步任务，计时结束，计算批量插入数据所消耗的时间：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 结束所有异步任务</span><br>CompletableFuture&lt;Void&gt; future = CompletableFuture.allOf(futureList.toArray(<span class="hljs-keyword">new</span> <span class="hljs-title class_">CompletableFuture</span>[]&#123;&#125;));<br>future.join();<br><span class="hljs-comment">// 计时结束</span><br>stopWatch.stop();<br><span class="hljs-comment">// 计算插入所用总时间</span><br>System.out.println(stopWatch.getTotalTimeMillis());<br></code></pre></td></tr></table></figure>

<h4 id="异步查询图片数据"><a href="#异步查询图片数据" class="headerlink" title="异步查询图片数据"></a>异步查询图片数据</h4><ul>
<li><p>这个需求场景是我在做 Memory 聚合搜索平台时遇到的：服务端聚合搜索不同来源的数据后返回</p>
</li>
<li><p>为每个搜索请求开启异步任务，并发执行<code>诗词搜索</code>、<code>博文搜索</code>和<code>图片搜索</code>三个任务：<strong>（2024/01/09晚）</strong></p>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 诗词搜索</span><br>CompletableFuture&lt;Page&lt;PostVO&gt;&gt; postTask = CompletableFuture.supplyAsync(() -&gt;<br>postDataSource.search(searchText, pageSize, current));<br><br><span class="hljs-comment">// 博文搜索</span><br>CompletableFuture&lt;Page&lt;ArticleVO&gt;&gt; articleTask = CompletableFuture.supplyAsync(() -&gt;<br>articleDataSource.search(searchText, pageSize, current));<br><br><span class="hljs-comment">// 图片搜索</span><br>CompletableFuture&lt;Page&lt;Picture&gt;&gt; pictureTask = CompletableFuture.supplyAsync(() -&gt;<br>pictureDataSource.search(searchText, pageSize, current));<br></code></pre></td></tr></table></figure>

<ul>
<li>结束所有异步任务，获取搜索结果：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java">CompletableFuture.allOf(postTask, pictureTask, articleTask).join();<br></code></pre></td></tr></table></figure>

<ul>
<li>整合不同搜索来源的搜索结果，返回聚合搜索结果：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">try</span> &#123;<br>    Page&lt;PostVO&gt; postVOPage = postTask.get();<br>    Page&lt;Picture&gt; picturePage = pictureTask.get();<br>    Page&lt;ArticleVO&gt; articlePage = articleTask.get();<br><br>    searchVO = <span class="hljs-keyword">new</span> <span class="hljs-title class_">SearchVO</span>();<br>    searchVO.setPostVOList(postVOPage.getRecords());<br>    searchVO.setPictureList(picturePage.getRecords());<br>    searchVO.setArticleList(articlePage.getRecords());<br><br>&#125; <span class="hljs-keyword">catch</span> (InterruptedException | ExecutionException e) &#123;<br>        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(e);<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="AI服务处理请求任务"><a href="#AI服务处理请求任务" class="headerlink" title="AI服务处理请求任务"></a>AI服务处理请求任务</h4><ul>
<li>这个需求场景是我在做 Memory BI智能分析平台 时遇到的：调用第三方AI服务处理用户请求</li>
<li>自定义线程池：<strong>（2024/01/09晚）</strong></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ThreadPoolExecutorConfig</span> &#123;<br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> ThreadPoolExecutor <span class="hljs-title function_">threadPoolExecutor</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-type">ThreadFactory</span> <span class="hljs-variable">threadFactory</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadFactory</span>() &#123;<br>            <span class="hljs-comment">// 记录线程数</span><br>            <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> <span class="hljs-variable">count</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br><br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-keyword">public</span> Thread <span class="hljs-title function_">newThread</span><span class="hljs-params">(<span class="hljs-meta">@NotNull</span> Runnable r)</span> &#123;<br>                <span class="hljs-type">Thread</span> <span class="hljs-variable">thread</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Thread</span>(r);<br>                thread.setName(<span class="hljs-string">&quot;线程&quot;</span> + count);<br>                count++;<br>                <span class="hljs-keyword">return</span> thread;<br>            &#125;<br>        &#125;;<br><br>        <span class="hljs-type">ThreadPoolExecutor</span> <span class="hljs-variable">threadPoolExecutor</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadPoolExecutor</span><br>                (<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">100</span>,<br>                        TimeUnit.MINUTES, <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayBlockingQueue</span>&lt;&gt;(<span class="hljs-number">4</span>), threadFactory);<br>        <span class="hljs-keyword">return</span> threadPoolExecutor;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>请求图表信息（图表名, 生成目标, 图表类型）：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-type">String</span> <span class="hljs-variable">name</span> <span class="hljs-operator">=</span> genChartByAiRequest.getName();<br><span class="hljs-type">String</span> <span class="hljs-variable">goal</span> <span class="hljs-operator">=</span> genChartByAiRequest.getGoal();<br><span class="hljs-type">String</span> <span class="hljs-variable">chartType</span> <span class="hljs-operator">=</span> genChartByAiRequest.getChartType();<br></code></pre></td></tr></table></figure>

<ul>
<li>校验用户登录：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-type">User</span> <span class="hljs-variable">loginUser</span> <span class="hljs-operator">=</span> userService.getLoginUser(request);<br>ThrowUtils.throwIf(loginUser == <span class="hljs-literal">null</span>, ErrorCode.NOT_LOGIN_ERROR, <span class="hljs-string">&quot;请先登录后再尝试调用接口&quot;</span>);<br></code></pre></td></tr></table></figure>

<ul>
<li>限流（限制用户的调用次数，以用户id为key，区分各个限流器）：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 3.限流(限制用户的调用次数，以用户id为key，区分各个限流器)</span><br>redisLimiterManager.doRateLimit(<span class="hljs-string">&quot;genCharByAi_&quot;</span> + loginUser.getId());<br></code></pre></td></tr></table></figure>

<ul>
<li>提取图表名信息、分析需求(分析目标 图表类型)，做好参数校验：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 4.1.校验图表名信息</span><br>ThrowUtils.throwIf(StringUtils.isNotBlank(name) &amp;&amp; name.length() &gt; <span class="hljs-number">100</span>, ErrorCode.PARAMS_ERROR, <span class="hljs-string">&quot;名称过长&quot;</span>);<br><span class="hljs-comment">// 4.2.校验分析目标</span><br>ThrowUtils.throwIf(StringUtils.isBlank(goal), ErrorCode.PARAMS_ERROR, <span class="hljs-string">&quot;分析目标为空&quot;</span>);<br><span class="hljs-comment">// 4.3.校验图表类型</span><br>ThrowUtils.throwIf(StringUtils.isBlank(chartType), ErrorCode.PARAMS_ERROR, <span class="hljs-string">&quot;分析图表类型为空&quot;</span>);<br></code></pre></td></tr></table></figure>

<ul>
<li>分析Excel图表，获取原始数据：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 5.1.校验文件</span><br><span class="hljs-comment">// 5.1.1.校验文件大小</span><br><span class="hljs-type">long</span> <span class="hljs-variable">size</span> <span class="hljs-operator">=</span> multipartFile.getSize();<br>ThrowUtils.throwIf(size &gt; ONE_MB, ErrorCode.PARAMS_ERROR, <span class="hljs-string">&quot;文件超过 1M&quot;</span>);<br><br><span class="hljs-comment">// 5.1.2.校验文件后缀</span><br><span class="hljs-type">String</span> <span class="hljs-variable">originalFilename</span> <span class="hljs-operator">=</span> multipartFile.getOriginalFilename();<br><span class="hljs-type">String</span> <span class="hljs-variable">suffix</span> <span class="hljs-operator">=</span> FileUtil.getSuffix(originalFilename);<br>ThrowUtils.throwIf(!VALID_FILE_SUFFIX_LIST.contains(suffix), ErrorCode.PARAMS_ERROR, <span class="hljs-string">&quot;文件后缀非法&quot;</span>);<br><br><span class="hljs-comment">// 5.2.分析文件，获取csv数据</span><br><span class="hljs-type">StringBuilder</span> <span class="hljs-variable">userInput</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">StringBuilder</span>();<br><span class="hljs-type">String</span> <span class="hljs-variable">excelToCsv</span> <span class="hljs-operator">=</span> ExcelUtils.excelToCsv(multipartFile);<br>userInput.append(<span class="hljs-string">&quot;\n&quot;</span>)<br>.append(<span class="hljs-string">&quot;分析需求:&quot;</span>).append(<span class="hljs-string">&quot;\n&quot;</span>)<br>.append(goal).append(<span class="hljs-string">&quot;, &quot;</span>).append(<span class="hljs-string">&quot;请生成一张&quot;</span>).append(chartType).append(<span class="hljs-string">&quot;\n&quot;</span>)<br>.append(<span class="hljs-string">&quot;原始数据:&quot;</span>).append(<span class="hljs-string">&quot;\n&quot;</span>)<br>.append(excelToCsv);<br></code></pre></td></tr></table></figure>

<ul>
<li>处理任务前, 先插入图表信息到数据库：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-type">Chart</span> <span class="hljs-variable">chart</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Chart</span>();<br>chart.setName(name);<br>chart.setGoal(goal);<br>chart.setChartType(chartType);<br>chart.setChartData(excelToCsv);<br>chart.setUserId(loginUser.getId());<br>chart.setStatus(ChartStatusEnum.WAIT.getValue());<br><span class="hljs-type">boolean</span> <span class="hljs-variable">save</span> <span class="hljs-operator">=</span> save(chart);<br>ThrowUtils.throwIf(!save, ErrorCode.OPERATION_DATABASE_ERROR, <span class="hljs-string">&quot;插入图表信息失败&quot;</span>);<br></code></pre></td></tr></table></figure>

<ul>
<li>使用任务队列处理任务：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// todo 建议处理任务队列满了之后, 抛出异常的情况</span><br>CompletableFuture.runAsync(() -&gt; &#123;<br>	<span class="hljs-comment">// 7.1.更新图表状态执行中(running)</span><br>	<span class="hljs-type">Chart</span> <span class="hljs-variable">updateChart</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Chart</span>();<br>	updateChart.setId(chart.getId());<br>	updateChart.setStatus(ChartStatusEnum.RUNNING.getValue());<br><br>	<span class="hljs-type">boolean</span> <span class="hljs-variable">updateById</span> <span class="hljs-operator">=</span> updateById(updateChart);<br>	ThrowUtils.throwIf(!updateById, ErrorCode.OPERATION_DATABASE_ERROR, <span class="hljs-string">&quot;更新图表执行中状态失败&quot;</span>);<br><br>	<span class="hljs-comment">// 7.2.AI 执行, 智能生成图表</span><br>	<span class="hljs-type">String</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> aiManager.doChat(AiConstant.BI_MODEL_ID, userInput.toString());<br><br>	<span class="hljs-comment">// 7.3.校验图表生成失败情况</span><br>	<span class="hljs-comment">// todo 校验图表生成失败情况</span><br>	<span class="hljs-keyword">if</span> (result == <span class="hljs-literal">null</span>) &#123;<br>	<span class="hljs-comment">// 更新图表信息(图表生成失败)</span><br>	<span class="hljs-type">Chart</span> <span class="hljs-variable">updateChartResult</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Chart</span>();<br>	updateChartResult.setId(chart.getId());<br>	updateChartResult.setStatus(ChartStatusEnum.FAILED.getValue());<br><br>	<span class="hljs-type">boolean</span> <span class="hljs-variable">updateResultById</span> <span class="hljs-operator">=</span> updateById(updateChartResult);<br>	ThrowUtils.throwIf(!updateResultById, ErrorCode.OPERATION_DATABASE_ERROR, <span class="hljs-string">&quot;更新图表失败状态失败&quot;</span>);<br>	&#125;<br><br>	<span class="hljs-comment">// 7.4.处理AI响应的对话信息</span><br>	String[] split = result.split(<span class="hljs-string">&quot;【【【【【&quot;</span>);<br>	<span class="hljs-type">String</span> <span class="hljs-variable">genChart</span> <span class="hljs-operator">=</span> split[<span class="hljs-number">1</span>];<br>	<span class="hljs-type">String</span> <span class="hljs-variable">genResult</span> <span class="hljs-operator">=</span> split[<span class="hljs-number">2</span>];<br><br>	<span class="hljs-comment">// 7.5.更新图表信息(图表成功状态、图表生成情况、图表分析结果)</span><br>	<span class="hljs-type">Chart</span> <span class="hljs-variable">updateChartResult</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Chart</span>();<br>	updateChartResult.setId(chart.getId());<br>	updateChartResult.setStatus(ChartStatusEnum.SUCCEED.getValue());<br>	updateChartResult.setGenChart(genChart);<br>	updateChartResult.setGenResult(genResult);<br><br>	<span class="hljs-type">boolean</span> <span class="hljs-variable">updateResultById</span> <span class="hljs-operator">=</span> updateById(updateChartResult);<br>	ThrowUtils.throwIf(!updateResultById, ErrorCode.OPERATION_DATABASE_ERROR, <span class="hljs-string">&quot;更新图表成功状态失败&quot;</span>);<br>&#125;, threadPoolExecutor);<br></code></pre></td></tr></table></figure>

<ul>
<li>封装分析结果并返回：<strong>（2024/01/09晚）</strong></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-type">BiResponse</span> <span class="hljs-variable">biResponse</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BiResponse</span>();<br>biResponse.setUserId(loginUser.getId());<br><br><span class="hljs-keyword">return</span> biResponse;<br></code></pre></td></tr></table></figure>

<h2 id="异步编程"><a href="#异步编程" class="headerlink" title="异步编程"></a>异步编程</h2><h3 id="CompletableFuture-简介"><a href="#CompletableFuture-简介" class="headerlink" title="CompletableFuture 简介"></a>CompletableFuture 简介</h3><h4 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h4><h4 id="优势与特点"><a href="#优势与特点" class="headerlink" title="优势与特点"></a>优势与特点</h4><h3 id="CompletableFuture-基本用法"><a href="#CompletableFuture-基本用法" class="headerlink" title="CompletableFuture 基本用法"></a>CompletableFuture 基本用法</h3><h4 id="小试牛刀"><a href="#小试牛刀" class="headerlink" title="小试牛刀"></a>小试牛刀</h4><ul>
<li><p>我们使用入门级案例，快速使用 CompletableFuture 对象执行异步编程：</p>
</li>
<li><h5 id="首先自定义线程：（2023-10-22晚）"><a href="#首先自定义线程：（2023-10-22晚）" class="headerlink" title="首先自定义线程：（2023/10/22晚）"></a>首先自定义线程：（2023/10/22晚）</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">ThreadTask</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">Runnable</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> <span class="hljs-variable">index</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">ThreadTask</span><span class="hljs-params">()</span> &#123;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">run</span><span class="hljs-params">()</span> &#123;<br>        Thread.currentThread().setName(<span class="hljs-string">&quot;MyThread: &quot;</span> + index++);<br>        System.out.println(Thread.currentThread().getName());<br>        <span class="hljs-keyword">try</span> &#123;<br>            Thread.sleep(<span class="hljs-number">3000</span>);<br>        &#125; <span class="hljs-keyword">catch</span> (InterruptedException e) &#123;<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(e);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="创建线程池，新增线程并使用-CompletableFuture-对象异步执行线程，实现并发："><a href="#创建线程池，新增线程并使用-CompletableFuture-对象异步执行线程，实现并发：" class="headerlink" title="创建线程池，新增线程并使用 CompletableFuture 对象异步执行线程，实现并发："></a>创建线程池，新增线程并使用 CompletableFuture 对象异步执行线程，实现并发：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">ThreadPool3</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">ThreadPoolExecutor</span> <span class="hljs-variable">threadPoolExecutor</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadPoolExecutor</span>(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>,<br>                <span class="hljs-number">1000</span>, TimeUnit.MILLISECONDS, <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayBlockingQueue</span>&lt;Runnable&gt;(<span class="hljs-number">4</span>),<br>                Executors.defaultThreadFactory(), <span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadPoolExecutor</span>.AbortPolicy());<br>        <span class="hljs-comment">// for (int i = 0; i &lt; 8; i++) &#123;</span><br>        <span class="hljs-comment">//     threadPoolExecutor.execute(new ThreadTask());</span><br>        <span class="hljs-comment">// &#125;</span><br>        <span class="hljs-comment">//</span><br>        <span class="hljs-comment">// for (int i = 0; i &lt; 8; i++) &#123;</span><br>        <span class="hljs-comment">//     Future&lt;?&gt; submit = threadPoolExecutor.submit(new ThreadTask());</span><br>        <span class="hljs-comment">// &#125;</span><br><br>        <span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">8</span>; i++) &#123;<br>            CompletableFuture.runAsync(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ThreadTask</span>(), threadPoolExecutor);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>在上面的代码中，我们还使用了<strong>三种方法</strong>来<strong>处理异步执行任务</strong>：</li>
</ul>
<blockquote>
<ul>
<li><code>threadPoolExecutor.execute(new ThreadTask())</code>: 这个方法将新的任务提交给线程池来执行。新的任务将创建一个新的线程来执行。如果线程池已满，新提交的任务将会等待现有任务完成后再开始执行。</li>
<li><code>Future&lt;?&gt; submit = threadPoolExecutor.submit(new ThreadTask())</code>: 这个方法将新的任务提交给线程池，但不立即执行，而是返回一个Future对象。Future对象表示任务的结果。在等待任务结果时，你还可以对其他任务进行调度，这是使用Future的优点。如果线程池已满，新提交的任务也会等待现有任务完成后再开始执行。</li>
<li><code>CompletableFuture.runAsync(new ThreadTask(), threadPoolExecutor)</code>: 这个方法用于提交一个异步任务到线程池中执行。这个方法创建了一个 CompletableFuture 对象，该对象允许你使用回调或future对象来等待任务的完成并获取结果。这种方法的优点是可以并发执行多个任务，无需等待上一个任务完成就开始下一个任务。</li>
</ul>
</blockquote>
<ul>
<li><h5 id="先简单了解一下吧，稍后我们会详细说明的（2023-10-22晚）"><a href="#先简单了解一下吧，稍后我们会详细说明的（2023-10-22晚）" class="headerlink" title="先简单了解一下吧，稍后我们会详细说明的（2023/10/22晚）"></a>先简单了解一下吧，稍后我们会详细说明的（2023/10/22晚）</h5></li>
<li><p>运行程序，得到执行结果如下：</p>
</li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20231022221903932.png" alt="image-20231022221903932"></p>
<h4 id="创建-CompletableFuture-对象"><a href="#创建-CompletableFuture-对象" class="headerlink" title="创建 CompletableFuture 对象"></a>创建 CompletableFuture 对象</h4><h4 id="获取任务结果"><a href="#获取任务结果" class="headerlink" title="获取任务结果"></a>获取任务结果</h4><h4 id="异步回调"><a href="#异步回调" class="headerlink" title="异步回调"></a>异步回调</h4><h4 id="多任务组合回调"><a href="#多任务组合回调" class="headerlink" title="多任务组合回调"></a>多任务组合回调</h4><h4 id="异常处理与错误处理"><a href="#异常处理与错误处理" class="headerlink" title="异常处理与错误处理"></a>异常处理与错误处理</h4><h4 id="自定义线程池与资源管理"><a href="#自定义线程池与资源管理" class="headerlink" title="自定义线程池与资源管理"></a>自定义线程池与资源管理</h4><h4 id="并发任务的调度与控制"><a href="#并发任务的调度与控制" class="headerlink" title="并发任务的调度与控制"></a>并发任务的调度与控制</h4><h4 id="IO操作与网络请求"><a href="#IO操作与网络请求" class="headerlink" title="IO操作与网络请求"></a>IO操作与网络请求</h4><h2 id="Java-锁机制"><a href="#Java-锁机制" class="headerlink" title="Java 锁机制"></a>Java 锁机制</h2><blockquote>
<h5 id="🔥-推荐阅读：（2023-10-24晚）"><a href="#🔥-推荐阅读：（2023-10-24晚）" class="headerlink" title="🔥 推荐阅读：（2023/10/24晚）"></a>🔥 推荐阅读：（2023/10/24晚）</h5><ul>
<li><h5 id="【多线程系列】终于懂了-Java-中的各种锁-掘金-juejin-cn"><a href="#【多线程系列】终于懂了-Java-中的各种锁-掘金-juejin-cn" class="headerlink" title="【多线程系列】终于懂了 Java 中的各种锁 - 掘金 (juejin.cn)"></a><a target="_blank" rel="noopener" href="https://juejin.cn/post/7276257296497147956">【多线程系列】终于懂了 Java 中的各种锁 - 掘金 (juejin.cn)</a></h5></li>
<li><h5 id="乐观锁和悲观锁详解-JavaGuide-Java面试-学习指南"><a href="#乐观锁和悲观锁详解-JavaGuide-Java面试-学习指南" class="headerlink" title="乐观锁和悲观锁详解 | JavaGuide(Java面试 + 学习指南)"></a><a target="_blank" rel="noopener" href="https://javaguide.cn/java/concurrent/optimistic-lock-and-pessimistic-lock.html">乐观锁和悲观锁详解 | JavaGuide(Java面试 + 学习指南)</a></h5></li>
</ul>
</blockquote>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul>
<li>悲观锁：悲观锁<strong>总是假设最坏的情况</strong>，认为在高并发情况下，共享变量每次被访问都会出现问题，所以每个线程在获取资源时都会加锁。激烈的锁竞争会导致线程阻塞和频繁的上下文切换，大大增加系统的性能开销，还可能引发死锁问题</li>
<li>乐观锁：乐观锁<strong>总是假设最好的情况</strong>，认为共享资源被访问时不会出现问题，线程无需加锁也无需等待，不存在锁竞争和线程阻塞。只需在提交修改时确认该资源是否被其他线程修改了，这就是验证线程之间是否发生冲突了，一般采用<strong>版本号机制</strong>或 <strong>CAS 算法实现</strong>。如果线程提交修改频繁失败、频繁重试，同样会大大增加系统性能开销。</li>
<li><strong>乐观锁还存在 ABA 问题</strong>，即错误地判断要修改的资源没有被其他线程修改，可以通过<strong>追加版本号</strong>或<strong>引入时间戳</strong>来解决</li>
<li>总体来说，悲观锁适用于<strong>写比较多</strong>的场景，避免频繁失败和频繁重试影响性能；乐观锁适用于<strong>写比较少</strong>的情况，避免频繁加锁影响性能<strong>（2023/10/27晚）</strong></li>
</ul>
<h1 id="亮点集锦"><a href="#亮点集锦" class="headerlink" title="亮点集锦"></a>亮点集锦</h1>
                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/categories/%E7%BA%BF%E7%A8%8B%E6%B1%A0/" class="category-chain-item">线程池</a>
  
  
    <span>></span>
    
  <a href="/categories/%E7%BA%BF%E7%A8%8B%E6%B1%A0/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/" class="category-chain-item">并发编程</a>
  
  
    <span>></span>
    
  <a href="/categories/%E7%BA%BF%E7%A8%8B%E6%B1%A0/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/JUC/" class="category-chain-item">JUC</a>
  
  
    <span>></span>
    
  <a href="/categories/%E7%BA%BF%E7%A8%8B%E6%B1%A0/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/JUC/%E7%BB%8F%E9%AA%8C/" class="category-chain-item">经验</a>
  
  

  

  

  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/tags/%E7%BA%BF%E7%A8%8B%E6%B1%A0/">#线程池</a>
      
        <a href="/tags/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/">#并发编程</a>
      
        <a href="/tags/JUC/">#JUC</a>
      
        <a href="/tags/%E7%BB%8F%E9%AA%8C/">#经验</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>Java线程池大揭秘：揭开并发编程的神秘面纱，让你的程序快到起飞</div>
      <div>http://example.com/2023/10/22/Java线程池大揭秘：揭开并发编程的神秘面纱，让你的程序快到起飞/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>Memory</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2023年10月22日</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>更新于</div>
          <div>2024年1月9日</div>
        </div>
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2023/10/24/Redis%20%E9%A3%8E%E6%9A%B4%EF%BC%9A%E4%BB%8E%E5%8E%9F%E7%90%86%E5%88%B0%E5%BA%94%E7%94%A8%EF%BC%8C%E4%B8%80%E6%8E%A2%E5%86%85%E5%AD%98%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%A5%A5%E7%A7%98/" title="Redis 风暴：从原理到应用，一探内存中的数据奥秘">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">Redis 风暴：从原理到应用，一探内存中的数据奥秘</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2023/10/09/%E4%B8%AA%E4%BA%BA%E6%88%90%E9%95%BF%E4%B9%8B%E8%B7%AF%EF%BC%9A%E8%AE%A1%E5%88%92%E6%BC%94%E8%BF%9B%E4%B8%8E%E6%80%9D%E6%83%B3%E8%9C%95%E5%8F%98%E7%9A%84%E8%A7%81%E8%AF%81/" title="个人成长之路：计划演进与思想蜕变的见证">
                        <span class="hidden-mobile">个人成长之路：计划演进与思想蜕变的见证</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
  
  
    <article id="comments">
      

    </article>
  


          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.fluid-dev.com/docs/guide/" target="_blank" rel="nofollow noopener"> <span>Memory | 个人文档站点</span> </a>
<i class="iconfont icon-love"></i> <a href="https://hexo.fluid-dev.com/docs/guide/" target="_blank" rel="nofollow noopener"> <span>配置指南 | Hexo Fluid 用户手册</span> </a>   
    </div>
  
  
    <div class="statistics">
  
  

  
    
      <span id="leancloud-site-pv-container" style="display: none">
        总访问量 
        <span id="leancloud-site-pv"></span>
         次
      </span>
    
    
      <span id="leancloud-site-uv-container" style="display: none">
        总访客数 
        <span id="leancloud-site-uv"></span>
         人
      </span>
    
    

  
</div>

  
  
    <!-- 备案信息 ICP for China -->
    <div class="beian">
  <span>
    <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
      京ICP证123456号
    </a>
  </span>
  
    
      <span>
        <a
          href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=12345678"
          rel="nofollow noopener"
          class="beian-police"
          target="_blank"
        >
          
            <span style="visibility: hidden; width: 0">|</span>
            <img src="/img/police_beian.png" alt="police-icon"/>
          
          <span>京公网安备12345678号</span>
        </a>
      </span>
    
  
</div>

  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>







  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.11/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/js/local-search.js" ></script>

  <script defer src="/js/leancloud.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
